﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AAA.Meta.Chart.Data;

namespace AAA.Chart.Data
{
    public class DefaultDataSource : IDataSource
    {
        private Dictionary<string, BarData> _dicBarData;
        private Dictionary<string, Dictionary<string, PriceVolumeData>> _dicPriceVolumeData;
        private Dictionary<string, List<string>> _dicPriceVolumeDate;
        private Dictionary<string, float> _dicLastPrice;
        private Dictionary<string, float> _dicLastVolume;

        public DefaultDataSource()
        {
            _dicBarData = new Dictionary<string, BarData>();
            _dicPriceVolumeData = new Dictionary<string, Dictionary<string, PriceVolumeData>>();
            _dicPriceVolumeDate = new Dictionary<string, List<string>>();
            _dicLastPrice = new Dictionary<string, float>();
            _dicLastVolume = new Dictionary<string, float>();
        }

        #region IDataSource Members

        public float LastPrice(string strSymbolId)
        {
            return _dicLastPrice.ContainsKey(strSymbolId)
                    ? _dicLastPrice[strSymbolId]
                    : -1;
        }

        public float LastVolume(string strSymbolId)
        {
            return _dicLastVolume.ContainsKey(strSymbolId)
                    ? _dicLastVolume[strSymbolId]
                    : -1;
        }

        public void AddTick(string strSymbolId, float fPrice, float fVolume)
        {
            if (_dicLastPrice.ContainsKey(strSymbolId))
                _dicLastPrice[strSymbolId] = fPrice;
            else
                _dicLastPrice.Add(strSymbolId, fPrice);

            if (_dicLastVolume.ContainsKey(strSymbolId))
                _dicLastVolume[strSymbolId] = fVolume;
            else
                _dicLastVolume.Add(strSymbolId, fVolume);
        }

        public List<string> SymbolList()
        {
            List<string> lstSymbol = new List<string>();

            foreach (string strSymbolId in _dicBarData.Keys)
                lstSymbol.Add(strSymbolId);

            return lstSymbol;
        }

        public bool ContainsSymbol(string strSymbolId)
        {
            return _dicBarData == null 
                        ? false 
                        : _dicBarData.ContainsKey(strSymbolId);
        }

        public BarData GetData(string strSymbolId)
        {
            return _dicBarData == null 
                    ? new BarData() 
                    :  _dicBarData.ContainsKey(strSymbolId) 
                        ? _dicBarData[strSymbolId] 
                        : new BarData();
        }

        private long CompareDate(string strSourceDate, string strTargetDate)
        {
            return DateTime.Parse(strSourceDate).Ticks - DateTime.Parse(strTargetDate).Ticks;
        }

        public PriceVolumeData GetPriceVolume(string strSymbolId, string strStartDate, string strEndDate)
        {
            PriceVolumeData priceVolume = new PriceVolumeData();

            if(_dicPriceVolumeData.ContainsKey(strSymbolId) == false)
                return priceVolume;

            Dictionary<string, PriceVolumeData> dicPriceVolume = _dicPriceVolumeData[strSymbolId];                        
            List<string> lstDate = _dicPriceVolumeDate[strSymbolId];
            int iStartIndex = 0;
            int iEndIndex = lstDate.Count;
            long lDiff;
            List<float> lstPrice;
            List<float> lstVolume;
            List<float> lstTickVolume;            
            lstDate.Sort();

            if (_dicPriceVolumeDate[strSymbolId].Count == 0)
                return priceVolume;

            if (((CompareDate(strStartDate, _dicPriceVolumeDate[strSymbolId][lstDate.Count - 1]) > 0) &&
                ((CompareDate(strEndDate, _dicPriceVolumeDate[strSymbolId][0]) < 0))))
                return priceVolume;

            for (int i = 0; i < lstDate.Count; i++)
            {
                lDiff = CompareDate(strStartDate, lstDate[i]);
                if (CompareDate(strStartDate, lstDate[i]) < 0)
                {
                    iStartIndex = i;
                    break;
                }
            }

            for (int i = iStartIndex; i < lstDate.Count; i++)
            {
                lDiff = CompareDate(strEndDate, lstDate[i]);
                if (CompareDate(strEndDate, lstDate[i]) < 0)
                {
                    iEndIndex = i;
                    break;
                }
            }

            /*
            iStartIndex = _dicPriceVolumeDate[strSymbolId].IndexOf(strStartDate) < 0
                            ? 0
                            : _dicPriceVolumeDate[strSymbolId].IndexOf(strStartDate);
            */                

            for (int i = iStartIndex; i < iEndIndex; i++)
            //for (int i = 0; i <= iStartIndex; i++)
            {
                lstPrice = dicPriceVolume[lstDate[i]].Price;
                lstVolume = dicPriceVolume[lstDate[i]].Volume;
                lstTickVolume = dicPriceVolume[lstDate[i]].TickVolume;

                for (int j = 0; j < lstPrice.Count; j++)
                    priceVolume.AddData(lstPrice[j], lstVolume[j], lstTickVolume[j]);
            }

            return priceVolume;
        }

        public PriceVolumeData GetPriceVolume(string strSymbolId)
        {
            return _dicPriceVolumeData == null
                                ? new PriceVolumeData()
                                : _dicPriceVolumeData.ContainsKey(strSymbolId) == false
                                    ? new PriceVolumeData()
                                    : _dicPriceVolumeData[strSymbolId].ContainsKey(_dicPriceVolumeDate[strSymbolId][_dicPriceVolumeDate[strSymbolId].Count - 1]) == false
                                        ? new PriceVolumeData()
                                        : _dicPriceVolumeData[strSymbolId][_dicPriceVolumeDate[strSymbolId][_dicPriceVolumeDate[strSymbolId].Count - 1]];
        }

        public int GetLength(string strSymbolId)
        {
            return _dicBarData == null
                        ? 0
                        : _dicBarData.ContainsKey(strSymbolId) 
                            ? _dicBarData[strSymbolId].GetLength() 
                            : 0;
        }

        public void AddSymbol(string strSymbolId, BarData barData)
        {
            if (_dicBarData.ContainsKey(strSymbolId))
                _dicBarData[strSymbolId] = barData;
            else
                _dicBarData.Add(strSymbolId, barData);
        }

        public void AddSymbol(string strSymbolId, Dictionary<string, PriceVolumeData> dicPriceVolumeData)
        {
            List<string> lstDate = new List<string>();

            if (_dicPriceVolumeData.ContainsKey(strSymbolId))
            {
                _dicPriceVolumeData[strSymbolId] = dicPriceVolumeData;
                _dicPriceVolumeDate[strSymbolId] = lstDate;
            }
            else
            {
                _dicPriceVolumeData.Add(strSymbolId, dicPriceVolumeData);
                _dicPriceVolumeDate.Add(strSymbolId, lstDate);
            }

            foreach (string strDate in dicPriceVolumeData.Keys)
                lstDate.Add(strDate);
            lstDate.Sort();

        }

        public void RemoveAllSymbol()
        {
            _dicBarData = new Dictionary<string, BarData>();
            _dicPriceVolumeData = new Dictionary<string, Dictionary<string, PriceVolumeData>>();
            _dicPriceVolumeDate = new Dictionary<string, List<string>>();
        }

        #endregion
    }
}
